package visiopuce.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;

import visiopuce.ApplicationContexte;
import visiopuce.HibernateUtil;
import visiopuce.DAO.ChampDAO;
import visiopuce.DAO.ChampDAOImpl;
import visiopuce.DAO.CotationDAO;
import visiopuce.DAO.CotationDAOImpl;
import visiopuce.DAO.HistoriqueDAO;
import visiopuce.DAO.HistoriqueDAOImpl;
import visiopuce.DAO.PrelevementDAO;
import visiopuce.DAO.PrelevementDAOImpl;
import visiopuce.DAO.TypeCotationDAOImpl;
import visiopuce.objets.Champ;
import visiopuce.objets.Cotation;
import visiopuce.objets.Historique;
import visiopuce.objets.Personne;
import visiopuce.objets.Prelevement;
import visiopuce.objets.Secteur;
import visiopuce.objets.TypeCotation;

public class PrelevementServiceImpl implements PrelevementService {

	private static final Log log = LogFactory.getLog(PrelevementService.class);

	private PrelevementDAO prelevementDAO = PrelevementDAOImpl.getInstance();
	private CotationDAO cotationDAO = CotationDAOImpl.getInstance();
	private ChampDAO champDAO = ChampDAOImpl.getInstance();
	private HistoriqueDAO historiqueDAO = HistoriqueDAOImpl.getInstance();

	/** Constructeur priv� */
	private PrelevementServiceImpl() {
	}

	/** Instance unique non pr�initialis�e */
	private static PrelevementServiceImpl INSTANCE = null;

	/** Point d'acc�s pour l'instance unique du singleton */
	public static PrelevementService getInstance() {
		if (INSTANCE == null) {
			INSTANCE = new PrelevementServiceImpl();
		}
		return INSTANCE;
	}

	public List<Prelevement> findAllByidPersonne(Integer idPersonne) {
		List<Prelevement> prelevements = null;

		HibernateUtil.beginTransaction();
		prelevements = prelevementDAO.findAllByidPersonne(idPersonne);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return prelevements;
	}

	public String[] getNumeroFromNumero(String numero) {
		String[] numeros = null;
		HibernateUtil.beginTransaction();
		numeros = (String[]) prelevementDAO.getNumeroFromNumero(numero);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return numeros;
	}

	public Prelevement getPrelevementByNumero(String numero) {
		Prelevement prelevement = null;

		HibernateUtil.beginTransaction();
		prelevement = prelevementDAO.getPrelevementByNumero(numero);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return prelevement;
	}

	public void save(Prelevement prelevement) throws HibernateException, Exception {
		HibernateUtil.beginTransaction();
		try {
			ArrayList<Cotation> cotations = new ArrayList<Cotation>();
			if (prelevement.getIdPrelevement() == 0) {
				if (prelevement.getTypePrelevement() != null) {
					if (prelevement.getNumeroPrelevement().equals("non reçu")) {
						prelevement.setNumeroPrelevement(genererNumeroPrelevement(prelevement, true));
					} else {
						prelevement.setNumeroPrelevement(genererNumeroPrelevement(prelevement, false));
					}
					ArrayList<String> listeCotation = ApplicationContexte.cotationReception;
					if (prelevement.getSecteur().getLibelle().contains("Puce")) {
						listeCotation.add("AQ002");
					}
					if (prelevement.getSecteur().getIdSecteur() == 1 || prelevement.getSecteur().getIdSecteur() == 2 || prelevement.getSecteur().getIdSecteur() == 4) {
						listeCotation.add("AN206");
					}
					
					if (prelevement.getTypePrelevement().getLibelle().contains("Sang")) {
						listeCotation.add("A9105");
					}
					if (prelevement.getSecteur().getLibelle().contains("Banque")) {
						listeCotation.add("AN206");
						listeCotation.add("AQ043");
					}
					for (String cotation : listeCotation) {
						List<TypeCotation> tc = TypeCotationDAOImpl.getInstance().getTypeCotation(cotation);
						Cotation c = new Cotation();
						c.setDate(new Date());
						c.setTypeCotation(tc.get(0));
						cotations.add(c);
					}
				} else {
					prelevement.setNumeroPrelevement("non reçu");
				}

			}
			if (prelevement.getNumeroPrelevement().equals("non reçu") || prelevement.getNumeroPrelevement().contains("tmp") && prelevement.getTypePrelevement() != null) {
				if (prelevement.getDateReception() != null) {
					prelevement.setNumeroPrelevement(genererNumeroPrelevement(prelevement, false));
				} else {
					prelevement.setNumeroPrelevement(genererNumeroPrelevement(prelevement, true));
				}

				ArrayList<String> listeCotation = ApplicationContexte.cotationReception;
				if (prelevement.getSecteur().getLibelle().contains("Puce")) {
					listeCotation.add("AQ002");
				}
				if (prelevement.getTypePrelevement().getLibelle().contains("Sang")) {
					listeCotation.add("A9105");
				}
				if (prelevement.getSecteur().getLibelle().contains("Banque")) {
					listeCotation.add("AN206");
					listeCotation.add("AQ043");
				}
				for (String cotation : listeCotation) {
					List<TypeCotation> tc = TypeCotationDAOImpl.getInstance().getTypeCotation(cotation);
					Cotation c = new Cotation();
					c.setDate(new Date());
					c.setTypeCotation(tc.get(0));
					cotations.add(c);
				}
			}
			prelevementDAO.save(prelevement);
			Historique h = new Historique();
			h.setDate(new Date());
			h.setRequete("Enregistrement " + prelevement.toString());
			h.setUtilisateur(ApplicationContexte.getInstance().getUtilisateur());
			historiqueDAO.save(h);

			// if (!prelevement.getNumeroPrelevement().equals("non reçu")) {
			// champDAO.deleteAllByidObjet("Prel-" +
			// prelevement.getIdPrelevement());
			// }
			ArrayList<Champ> champs = prelevement.getChamps();
			if (champs != null && champs.size() > 0) {
				champDAO.deleteAllByidObjet("Prel-" + prelevement.getIdPrelevement());
				Historique h4 = new Historique();
				h4.setDate(new Date());
				h4.setRequete("Suppression des champs de l'objet" + "Prel-" + prelevement.getIdPrelevement());
				h4.setUtilisateur(ApplicationContexte.getInstance().getUtilisateur());
				historiqueDAO.save(h4);

				if (champs != null) {
					for (Champ champ : champs) {
						Champ champOld = champDAO.getChampByTypeAndIdObjet(champ.getType(), "Prel-" + prelevement.getIdPrelevement());
						if (champOld != null) {
							champOld.setValeur(champ.getValeur());
							champ = champOld;
						} else {
							champ.setIdObjet("Prel-" + prelevement.getIdPrelevement());
						}
						if (champ.getType().equals("tTypeADN") && champ.getValeur().contains("Purification")) {
							addCotation(prelevement, cotations, "AN018");
							addCotation(prelevement, cotations, "AN014");
						}
						if (champ.getType().equals("tTypeADN") && champ.getValeur().contains("Extraction")) {
							addCotation(prelevement, cotations, "AQ048");
							if (prelevement.getSecteur().getIdSecteur() == 9) {
								addCotation(prelevement, cotations, "AN923");
							} else {
								addCotation(prelevement, cotations, "AQ901");
							}
						}
						champDAO.save(champ);
						Historique h2 = new Historique();
						h2.setDate(new Date());
						h2.setRequete("Enregistrement " + champ.toString());
						h2.setUtilisateur(ApplicationContexte.getInstance().getUtilisateur());
						historiqueDAO.save(h2);
					}
				}
			}
			for (Cotation cotation : cotations) {
				cotation.setPrelevement(prelevement);
				CotationServiceImpl.getInstance().save(cotation);
			}
			HibernateUtil.commitTransaction();
		} catch (Exception ex) {
			ex.printStackTrace();
			HibernateUtil.rollbackTransaction();
		} finally {
			HibernateUtil.closeSession();
		}
	}

	private ArrayList<Cotation> addCotation(Prelevement prelevement, ArrayList<Cotation> cotations, String code) {
		List<Cotation> c = CotationDAOImpl.getInstance().getCotationByPrelevementAndLibelle(prelevement.getIdPrelevement(), code);
		if (c == null || c.size() == 0) {
			Cotation cotQ901 = new Cotation();
			cotQ901.setDate(new Date());
			ArrayList<TypeCotation> tc = TypeCotationDAOImpl.getInstance().getTypeCotation(code);
			cotQ901.setTypeCotation(tc.get(0));
			cotations.add(cotQ901);
		}
		return cotations;
	}

	private String genererNumeroPrelevement(Prelevement prelevement, boolean isTemp) {

		String numero = "";
		if (prelevement.getDerive() != null) {

			if (prelevement.getDerive().getNumeroPrelevement().contains("P")) {
				int numeroCourrant = 0;

				Calendar c = Calendar.getInstance();
				int year = c.get(Calendar.YEAR);

				String debut = getLettre(prelevement, isTemp) + (year - 2000);
				String[] numeros = null;
				numeros = (String[]) prelevementDAO.getNumeroFromNumero(debut);
				if (numeros != null) {

					for (int i = 0; i < numeros.length; i++) {
						int tiret = numeros[i].indexOf("-");
						if (numeros[i].length() >= tiret + 5) {
							Integer num = Integer.parseInt(numeros[i].substring(tiret + 1, tiret + 5));

							if (num > numeroCourrant) {
								numeroCourrant = Integer.parseInt(numeros[i].substring(tiret + 1, tiret + 5));
							}
						} else {
							System.out.println(numeros[i]);
						}
					}
				}
				numeroCourrant = numeroCourrant + 1;
				String zeros = "";
				int nbZero = 4 - ("" + numeroCourrant).length();
				for (int i = 0; i < nbZero; i++) {
					zeros += "0";
				}
				numero = debut + "-" + zeros + numeroCourrant;
			} else {
				Prelevement p2 = prelevementDAO.getPrelevementByNumero(prelevement.getDerive().getNumeroPrelevement() + "-2");
				if (p2 != null) {
					Prelevement p3 = prelevementDAO.getPrelevementByNumero(prelevement.getDerive().getNumeroPrelevement() + "-3");
					if (p3 != null) {
						Prelevement p4 = prelevementDAO.getPrelevementByNumero(prelevement.getDerive().getNumeroPrelevement() + "-4");
						if (p4 != null) {
							Prelevement p5 = prelevementDAO.getPrelevementByNumero(prelevement.getDerive().getNumeroPrelevement() + "-5");
							if (p5 == null) {
								numero = prelevement.getDerive().getNumeroPrelevement() + "-5";
							}
						} else {
							numero = prelevement.getDerive().getNumeroPrelevement() + "-4";
						}
					} else {
						numero = prelevement.getDerive().getNumeroPrelevement() + "-3";
					}
				} else {
					numero = prelevement.getDerive().getNumeroPrelevement() + "-2";
				}

			}
		} else {
			int numeroCourrant = 0;

			Calendar c = Calendar.getInstance();
			int year = c.get(Calendar.YEAR);

			String debut = getLettre(prelevement, isTemp) + (year - 2000);
			String[] numeros = null;
			numeros = (String[]) prelevementDAO.getNumeroFromNumero(debut);
			if (numeros != null) {

				for (int i = 0; i < numeros.length; i++) {
					int tiret = numeros[i].indexOf("-");
					if (numeros[i].length() >= tiret + 5) {
						Integer num = Integer.parseInt(numeros[i].substring(tiret + 1, tiret + 5));

						if (num > numeroCourrant) {
							numeroCourrant = Integer.parseInt(numeros[i].substring(tiret + 1, tiret + 5));
						}
					} else {
						System.out.println(numeros[i]);
					}
				}
			}
			numeroCourrant = numeroCourrant + 1;
			String zeros = "";
			int nbZero = 4 - ("" + numeroCourrant).length();
			for (int i = 0; i < nbZero; i++) {
				zeros += "0";
			}
			numero = debut + "-" + zeros + numeroCourrant;
		}
		return numero;
	}

	private String getLettre(Prelevement prelevement, boolean isTemp) {
		String lettre = "F";
		if (prelevement.getSecteur().getLibelle().equals(ApplicationContexte.SECTEUR_PUCE_POSTNATAL) || prelevement.getSecteur().getLibelle().equals(ApplicationContexte.SECTEUR_PUCE_PRENATAL) || prelevement.getSecteur().getLibelle().equals(ApplicationContexte.SECTEUR_PUCE_FOETO)) {
			lettre = "A";
		} else if (prelevement.getSecteur().getLibelle().equals(ApplicationContexte.SECTEUR_BANQUE)) {
			lettre = "P";
		} else if (prelevement.getSecteur().getLibelle().equals(ApplicationContexte.SECTEUR_PRENATAL) || prelevement.getSecteur().getLibelle().equals(ApplicationContexte.SECTEUR_POSTNATAL) || prelevement.getSecteur().getLibelle().equals(ApplicationContexte.SECTEUR_FOETO)) {
			if (prelevement.getTypePrelevement().getIdTypePrelevement() == 1 || prelevement.getTypePrelevement().getIdTypePrelevement() == 18 || prelevement.getTypePrelevement().getIdTypePrelevement() == 21) {
				lettre = "S";
			} else if (prelevement.getTypePrelevement().getIdTypePrelevement() == 3 || prelevement.getTypePrelevement().getIdTypePrelevement() == 7 || prelevement.getTypePrelevement().getIdTypePrelevement() == 13) {
				lettre = "LA";
			} else if (prelevement.getTypePrelevement().getIdTypePrelevement() == 2 || prelevement.getTypePrelevement().getIdTypePrelevement() == 19) {
				lettre = "SF";
			} else if (prelevement.getTypePrelevement().getIdTypePrelevement() == 4 || prelevement.getTypePrelevement().getIdTypePrelevement() == 8) {
				lettre = "VC";
			}
		} else if (prelevement.getSecteur().getLibelle().equals(ApplicationContexte.SECTEUR_CELLULES)) {
			lettre = "CS";
		}
		if (isTemp) {
			lettre = "tmp" + lettre;
		}
		return lettre;
	}

	public ArrayList<Prelevement> getAutrePrelevementFromPatient(Prelevement prelevement) {
		ArrayList<Prelevement> prelevementsFinal = new ArrayList<Prelevement>();
		List<Prelevement> prelevements = null;

		HibernateUtil.beginTransaction();
		prelevements = prelevementDAO.findAllByidPersonne(prelevement.getPersonne().getIdPersonne());
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		for (Prelevement prelevementsCourrant : prelevements) {
			if (prelevementsCourrant.getIdPrelevement() != prelevement.getIdPrelevement()) {
				prelevementsFinal.add(prelevementsCourrant);
			}
		}

		return prelevementsFinal;
	}

	public Champ getChampByTypeAndIdObjet(String type, String idObjet) {
		Champ champ = null;
		HibernateUtil.beginTransaction();
		champ = champDAO.getChampByTypeAndIdObjet(type, idObjet);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return champ;
	}

	public Prelevement refresh(Prelevement prelevement) {
		if (prelevement.getIdPrelevement() != 0) {
			HibernateUtil.beginTransaction();
			HibernateUtil.getSession().refresh(prelevement);
			HibernateUtil.closeSession();
		}
		return prelevement;
	}

	@Override
	public Prelevement getPrelevementById(int idPrelevement) {
		Prelevement p = null;
		HibernateUtil.beginTransaction();
		p = prelevementDAO.findByID(Prelevement.class, idPrelevement);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return p;
	}

	@Override
	public Secteur getSecteurByIdPrelevement(Integer idPrelevement) {
		Secteur s = null;
		HibernateUtil.beginTransaction();
		s = prelevementDAO.getSecteurByIdPrelevement(idPrelevement);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return s;
	}

	@Override
	public Prelevement getPrelevementByPersonneSecteur(Integer idPersonne, int idSecteur) {
		Prelevement p = null;
		HibernateUtil.beginTransaction();
		p = prelevementDAO.getPrelevementByPersonneSecteur(idPersonne, idSecteur);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return p;
	}

	@Override
	public List<Prelevement> getPrelevementByNomFichier(String fichier) {
		List<Prelevement> p = new ArrayList<Prelevement>();
		HibernateUtil.beginTransaction();
		p = prelevementDAO.getPrelevementByLettre(fichier.substring(0, fichier.indexOf('.')));
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return p;
	}

	@Override
	public void delete(Prelevement prelevement) {
		HibernateUtil.beginTransaction();
		try {
			List<Cotation> cotations = CotationDAOImpl.getInstance().getCotationByidPrelevement(prelevement.getIdPrelevement());

			for (Cotation cotation : cotations) {
				Historique h2 = new Historique();
				h2.setDate(new Date());
				h2.setRequete("Suppression " + cotation.toString());
				h2.setUtilisateur(ApplicationContexte.getInstance().getUtilisateur());
				historiqueDAO.save(h2);
				CotationDAOImpl.getInstance().delete(cotation);
			}
			Historique h3 = new Historique();
			h3.setDate(new Date());
			h3.setRequete("Suppression " + prelevement.toString());
			h3.setUtilisateur(ApplicationContexte.getInstance().getUtilisateur());
			historiqueDAO.save(h3);

			prelevementDAO.delete(prelevement);

			HibernateUtil.commitTransaction();
		} catch (Exception ex) {
			ex.printStackTrace();
			HibernateUtil.rollbackTransaction();
		} finally {
			HibernateUtil.closeSession();
		}
	}

	@Override
	public HashMap<String, String> getChampByIdObjet(String idObj) {
		List<Champ> champs = null;
		HashMap<String, String> champsOut = new HashMap<String, String>();
		HibernateUtil.beginTransaction();
		champs = champDAO.getChampIdObjet(idObj);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		for (Champ champ2 : champs) {
			champsOut.put(champ2.getType(), champ2.getValeur());
		}
		return champsOut;
	}

	@Override
	public String[] getUFPrescs() {
		HibernateUtil.beginTransaction();
		List luFPResc = prelevementDAO.getAllUFPresc();
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		Object[] ouFPResc = (Object[]) luFPResc.toArray();
		String[] uFPResc = new String[ouFPResc.length];
		for (int i = 0; i < ouFPResc.length; i++) {
			if (ouFPResc[i] != null) {
				uFPResc[i] = ((Integer) ouFPResc[i]).toString();
			} else {
				uFPResc[i] = "0";
			}
		}
		return uFPResc;
	}

	// public Personne numSejourUnique(String numSejour, Integer idPersonne) {
	// Personne p = null;
	// HibernateUtil.beginTransaction();
	// p = personneDAO.numSejourUnique(numSejour, idPersonne);
	// HibernateUtil.commitTransaction();
	// return p;
	// }

	@Override
	public Personne getPersonneByIEP(String nda) {
		Personne personne = null;
		HibernateUtil.beginTransaction();
		personne = prelevementDAO.getPersonneByIEP(nda);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return personne;
	}

	@Override
	public List<String> getNumSejourNonTermine() {
		List<String> p = new ArrayList<String>();
		HibernateUtil.beginTransaction();
		p = prelevementDAO.getNumSejourNonTermine();
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return p;
	}

	@Override
	public List<Prelevement> getPrelevementByNumSejour(String numSejour) {
		List<Prelevement> p = new ArrayList<Prelevement>();
		HibernateUtil.beginTransaction();
		p = prelevementDAO.getPrelevementByNumSejour(numSejour);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return p;
	}

	@Override
	public List<String> getNumSejourCotationAEnvoyer() {
		List<String> p = new ArrayList<String>();
		HibernateUtil.beginTransaction();
		p = prelevementDAO.getNumSejourCotationAEnvoyer();
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return p;
	}
}